//
//  File.swift
//  Documentation
//
//  Created by Toj on 10/17/23.
//

DRM - Apple - FairPlay
自从2013年苹果引入App DRM机制
2020年发布的M1 Mac将Fairplay DRM机制引入了MacOS

1. 什么是 Apple FairPlay?
FairPlay 是 Apple 公司的 DRM 解决方案, 它使用 HLS 协议安全地传输流媒体。
iOS, tvOS 和 macOS 原生支持 FairPlay DRM

2. FairPlay DRM 的重要构成

FairPlay 主要模块:
2.1 HLS 打包器:
在加密视频之前, 必须先使用 HLS 协议打包视频.
HLS 是 Apple 公司2016年引入的 开发的流媒体协议, 用于 ABR 转码技术, 并且支持 MPEG-TS(ts)或者分段 mp4(fmp4)容器格式的文件存储

2.2 使用 SAMPLE-AES 和 AES-128 加密

接着必须使用 AES-128 CBC 模式加密内容
CBC(Cipher Block Chaining): 即密文分组链接
CBC 模式通过上一个分组加密输出影响当前分组.

使用初始化向量(IV), 可以确保即使同一明文(输入)用同一密钥被独立加密数次, 也能生成不同的密文(加密过程中的输出).
IV: Initialization Vector 初始化向量
IV 是随机的, 这样可以阻止黑客通过观察密文, 识别重复模式并获取密钥.

通过 Apple FairPlay, 你可以使用 SAMPLE-AES 或 AES-128 视频加密技术.
这两种技术都使用了 AES-128 加密, 只是应用在视频上的方式不同.

2.2.1 SAMPLE-AES 技术
为了资源开销
无需整个文件加密, 只需使用AES-128 的CBC模式加密音频数据包和视频帧的 sample
这样节省加密和解密过程中的功耗(尤其在视频分辨率增加的情况下)

比如:
FairPlay 协议规定, 在 H.264/AVC 码流中,
如果 NAL 单元类型是 1 或 5, 那么 NAL 就会被加密; 其他情况则不会被加密.
为什么? 因为单元类型为 1 和 5 的时候, NAL 包含了非 IDR 和 IDR 帧信息.
在视频编解码器的码流中, IDR 帧代表了新的视频切片的开始.
没有 IDR 帧, 其他帧就无法被解码(直到下一个 IDR 或者 I 帧到达)
这说明了 SAMPLE-AES 的目标是加密一小部分有价值的音视频内容, 以节省处理资源和电池电量.

下面是 m3u8 播放清单中 SAMPLE-AES 的表示方式:
EXT-X-KEY 显示: SAMPLE-AES
后接内容密钥(Content Key的 URI)
IV(初始化向量)和密钥一起使用

#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:9.96,
#EXT-X-KEY:METHOD=SAMPLE-AES,URI="https://dummyurl/test.key",IV=0x73fbe3277bdf0bfc5217125bde4ca589
test_0.ts
#EXTINF:10,
test_1.ts
#EXTINF:10,

2.2.2 AES-128 技术
切片（包括音频和视频）通过 AES-128、CBC 模式和 PKCS7 填充(Public-Key Cryptography Standards, 公钥密码标准)完全加密.
通过 IV 或者媒体序列号(代替 IV), CBC 在每个切片边界处重新启动

下面是 AES-128 在 m3u8 文件中的表示方式:
EXT-X-KEY 显示: AES-128
后接内容密钥的 URI
IV(初始化向量)和密钥一起使用

#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-VERSION:3
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:9.96,
#EXT-X-KEY:METHOD=AES-128,URI="https://dummyurl/test.key",IV=0x73fbe3277bdf0bfc5217125bde4ca589
test_0.ts
#EXTINF:10,
test_1.ts
#EXTINF:10,


3. FairPlay DRM 工作原理
第 1 步： 用户打开内容提供商的 App，然后按下 “播放键”，开始观看某部电影。

第 2 步： 应用通知 AVFoundation 它需要播放视频，并向 HLS 视频流提供 m3u8 播放列表的详细信息。

第 3 步： AVFoundation 下载并解析 m3u8 文件。

第 4 步： AVFoundation 在 m3u8 中搜索 #EXT-X-KEY，以检查视频是否被加密。
如果内容已被加密，AVFoundation 将向 AVFoundation App Delegate 请求内容密钥并解密内容。

第 5 步： 作为回应，App Delegate 向 AVFoundation 框架请求生成 SPC 信息。
来自播放器的请求被称为SPC（Server Playback Context，服务器播放上下文）。

第 6 步： 收到来自 AVFoundation 的 SPC 后，App Delegate 将其发送给密钥服务器。
密钥服务器中的 KSM 打开 SPC
KSM: Key Security Module
密钥服务器使用 SPC 中的信息查找内容密钥
发送内容密钥至 KSM，KSM 将其放入 CKC中
CKC: Content Key Context

第 7 步： KSM 向 AVFoundation App Delegate 发送 CKC。App Delegate 将 CKC 推送至 AVFoundation 中。

第 8 步： AVFoundation 使用 CKC 中的内容密钥解密、解码，然后向用户安全地播放内容。
以上就是 FairPlay DRM 的基本工作流程。

接下来，我们一起来了解 FairPlay 中几个有趣的功能。

获取加密密钥的 AVContentKeySession
AVContentKeySession 是 AVFoundation 中处理解密密钥的工具，于 WWDC 2017 宣布推出。
它提供了对内容密钥加载和生命周期的更多控制，目标是将密钥加载与媒体播放生命周期解耦。

为什么 AVContentKeySession 如此重要？
在基本的 FairPlay 工作流中，播放开始后才加载内容密钥。
在用户体验方面，这意味着用户需要等待 SPC-CKC 工作流完成之后才开始播放视频。
这种等待增加了 “首屏延迟（Startup Delay）” 和 “延迟（Latency）”，对终端用户很不友好。
然而，使用 AVContentKeySession,，
应用程序就可以在用户按下播放键之前请求内容密钥（被称为 “密钥预加载”）。
通过预加载密钥，内容提供商可以减少首屏延迟（延迟）并提升用户体验。
视频租赁的双到期时间窗口

Apple FairPlay 还拥有 “双到期时间窗口（Dual Expiry Windows）”，
这一功能可以和持久密钥（Persistent Key）结合使用实现离线播放。
持久密钥是指密钥可以：
安全地存储在设备上。
在预定义时间段播放租赁内容，而无需联系许可证服务器（离线播放）。
在租赁商业模式中，需要这样定义两个到期窗口：

第一个窗口： 当用户租借电影时，电影可以在 30 天的时间窗口内观看（举例）。
第二个窗口： 用户一按下播放键，电影必须在 48 小时内观看。第二个时间窗口到期后，30 天的时间窗口也会到期。

为了说明这种租赁模式，FairPlay 推出了 “双到期时间窗口” 这一功能，其中：

来自许可证服务器中的第一个密钥确立了更长的租赁期（存储期）。

第二个密钥在用户开始播放视频时获得，它取代了第一个密钥（播放期）。当超过第二个密钥的过期窗口，用户就无法访问或者播放视频内容了。

假设用户在租赁电影后，从来没有观看过。在这种情况下，电影的第一个密钥成为系统上的唯一密钥，超过有效期后它会自动失效。


4. iOS DRM - FairPlay 应用

1. 苹果为了保护App Store分发的音乐/视频/书籍/App免于盗版，开发了Fairplay DRM技术，并申请了很多相关的专利, 这样可以保证App无法使用Hopper等反编译静态分析,无法Class-Dump.
*** 在逆向分析过程中需要对加密的二进制文件进行解密才可以进行静态分析, 这一过程就是大家熟知的砸壳(脱壳)
砸壳工具有:
Stefanesser的【Dumpdecrypted】，
Monkey的【frida-ios-dump】

砸壳原理:
那么这些工具解密的原理是什么呢?
iOS/macOS 系统中, 可执行文件、动态库等, 都使用 DYLD 加载执行.
在 iOS 系统中使用 DYLD 载入 App 时, 会先进行 DRM 检查, 检查通过则从 App 的可执行文件中, 选择适合当前设备架构的 Mach-O 镜像进行解密,
然后载入内存执行, 这个程序并没有解密的逻辑, 当他被执行时, 其实加载器已经完成了目标mach-o文件的装载工作, 对应的解密工作也已经完成.
解密工具本身并不做解密, 这些工具所做的工作是, 遍历loadcommand中所有LC_ENCRYPTION_INFO或LC_ENCRYPTION_INFO_64的信息,
将对应解密后的数据从内存中dump出来, 复写到mach-o文件中, 生成新的镜像文件, 从而达到解密的效果.

简单来说，就是在App运行的过程中, 将内存中的已经解密的二进制文件拷贝出来, 生成新的镜像文件.
参考文章地址:
https://www.jianshu.com/p/786276bbced9?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

iOS逆向工程之工具安装:
https://www.jianshu.com/p/09aa48ceff4f

2. 音视频资源增加FairPlay验证
